package com.engine.salary.web;

import com.engine.common.util.ServiceUtil;
import com.engine.salary.entity.config.SalaryConfig;
import com.engine.salary.sys.entity.param.*;
import com.engine.salary.sys.entity.po.SalarySysConfPO;
import com.engine.salary.sys.entity.vo.AppSettingVO;
import com.engine.salary.sys.entity.vo.OrderRuleVO;
import com.engine.salary.sys.entity.vo.UploadConfigResponse;
import com.engine.salary.sys.enums.TaxDeclarationFunctionEnum;
import com.engine.salary.util.ResponseResult;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.xml.XStreamUtil;
import com.engine.salary.wrapper.SalarySystemConfigWrapper;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import lombok.extern.slf4j.Slf4j;
import weaver.hrm.HrmUserVarify;
import weaver.hrm.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.Map;

@Slf4j
public class SalarySystemConfigController {

    private SalarySystemConfigWrapper getSalarySystemConfigWrapper(User user) {
        return ServiceUtil.getService(SalarySystemConfigWrapper.class, user);
    }

    /**
     * 获取系统基础配置
     *
     * @param request
     * @param response
     * @return
     */
    @GET
    @Path("/info")
    @Produces(MediaType.APPLICATION_JSON)
    public String info(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Map<String, Object>, Map<String, Object>>(user).run(getSalarySystemConfigWrapper(user)::info);
    }

    /**
     * 是否开启系统算税
     *
     * @param request
     * @param response
     * @param param
     * @return
     */
    @POST
    @Path("/operateTaxDeclarationFunction")
    @Produces(MediaType.APPLICATION_JSON)
    public String operateTaxDeclarationFunction(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody AppSettingSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);

        return new ResponseResult<TaxDeclarationFunctionEnum, Boolean>(user).run(getSalarySystemConfigWrapper(user)::operateTaxDeclarationFunction, TaxDeclarationFunctionEnum.parseByValue(param.getOperateTaxDeclaration()));
    }


    /**
     * 获取系统配置
     *
     * @param request
     * @param response
     * @param code
     * @return
     */
    @GET
    @Path("/conf/code")
    @Produces(MediaType.APPLICATION_JSON)
    public String info(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "code") String code) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<String, String>(user).run(getSalarySystemConfigWrapper(user)::getOneByCode, code);
    }

    /**
     * 获取系统配置
     *
     * @param request
     * @param response
     * @return
     */
    @POST
    @Path("/list")
    @Produces(MediaType.APPLICATION_JSON)
    public String info(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalarySysConfQueryParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalarySysConfQueryParam, PageInfo<SalarySysConfPO>>(user).run(getSalarySystemConfigWrapper(user)::list, param);
    }

    /**
     * 系统配置详情
     *
     * @param request
     * @param response
     * @return
     */
    @GET
    @Path("/detail")
    @Produces(MediaType.APPLICATION_JSON)
    public String detail(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "id") Long id) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<Long, SalarySysConfPO>(user).run(getSalarySystemConfigWrapper(user)::detail, id);
    }


    /**
     * 保存系统配置
     *
     * @param request
     * @param response
     * @return
     */
    @POST
    @Path("/save")
    @Produces(MediaType.APPLICATION_JSON)
    public String save(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalarySysConfPO param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalarySysConfPO, String>(user).run(getSalarySystemConfigWrapper(user)::save, param);
    }

    /**
     * 更新系统配置
     *
     * @param request
     * @param response
     * @return
     */
    @POST
    @Path("/update")
    @Produces(MediaType.APPLICATION_JSON)
    public String update(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalarySysConfPO param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalarySysConfPO, String>(user).run(getSalarySystemConfigWrapper(user)::update, param);
    }

    /**
     * 新增或更新系统配置
     *
     * @param request
     * @param response
     * @return
     */
    @POST
    @Path("/operate")
    @Produces(MediaType.APPLICATION_JSON)
    public String operate(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalarySysConfPO param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalarySysConfPO, String>(user).run(getSalarySystemConfigWrapper(user)::operate, param);
    }


    /**
     * 单个规则配置
     *
     * @param request
     * @param response
     * @param param
     * @return
     */
    @POST
    @Path("/updateByCode")
    @Produces(MediaType.APPLICATION_JSON)
    public String updateByCode(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalarySysConfPO param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalarySysConfPO, String>(user).run(getSalarySystemConfigWrapper(user)::updateByCode, param);
    }

    @POST
    @Path("/updateOrderRule")
    @Produces(MediaType.APPLICATION_JSON)
    public String updateOrderRule(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody OrderRuleParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<OrderRuleParam, String>(user).run(getSalarySystemConfigWrapper(user)::updateOrderRule, param);
    }

    @GET
    @Path("/orderRule")
    @Produces(MediaType.APPLICATION_JSON)
    public String updateOrderRule(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<OrderRuleParam, OrderRuleVO>(user).run(getSalarySystemConfigWrapper(user)::orderRule);
    }

    @POST
    @Path("/saveMatchEmployeeModeRule")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveMatchEmployeeModeRule(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody MatchEmployeeModeSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<MatchEmployeeModeSaveParam, String>(user).run(getSalarySystemConfigWrapper(user)::saveMatchEmployeeModeRule, param);
    }

    /**
     * 薪资核算人员匹配规则
     *
     * @param request
     * @param response
     * @param param
     * @return
     */
    @POST
    @Path("/saveSalaryAcctEmployeeRule")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveSalaryAcctEmployeeRule(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody MatchEmployeeModeSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<String, String>(user).run(getSalarySystemConfigWrapper(user)::saveSalaryAcctEmployeeRule, param.getRule());
    }

    /**
     * 工资单反馈
     *
     * @param request
     * @param response
     * @param param
     * @return
     */
    @POST
    @Path("/saveSalarySendFeedback")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveSalarySendFeedback(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalarySysConfPO param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalarySysConfPO, String>(user).run(getSalarySystemConfigWrapper(user)::saveSalarySendFeedback, param);
    }

    /**
     * 撤回个税申报
     *
     * @param request
     * @param response
     * @param param
     * @return
     */
    @POST
    @Path("/saveWithDrawTaxDeclaration")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveWithDrawTaxDeclaration(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalarySysConfPO param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<SalarySysConfPO, String>(user).run(getSalarySystemConfigWrapper(user)::saveWithDrawTaxDeclaration, param);
    }

    /**
     * 删除档案
     *
     * @param request
     * @param response
     * @param param
     * @return
     */
    @POST
    @Path("/saveArchiveDelete")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveArchiveDelete(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody SalarySysConfPO param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<String, String>(user).run(getSalarySystemConfigWrapper(user)::saveArchiveDelete, param.getConfValue());
    }

    /**
     * 应用设置
     *
     * @param request
     * @param response
     * @param param
     * @return
     */
    @POST
    @Path("/app/setting/save")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveAppSetting(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody AppSettingSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<AppSettingSaveParam, String>(user).run(getSalarySystemConfigWrapper(user)::saveAppSetting, param);
    }

    /**
     * 应用设置
     *
     * @param request
     * @param response
     * @param param
     * @return
     */
    @POST
    @Path("/app/setting/saveEncryptSetting")
    @Produces(MediaType.APPLICATION_JSON)
    public String saveEncryptSetting(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody AppSettingSaveParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<AppSettingSaveParam, Map<String, Object>>(user).run(getSalarySystemConfigWrapper(user)::saveEncryptSetting, param);
    }

    /**
     * 应用设置
     *
     * @param request
     * @param response
     * @return
     */
    @GET
    @Path("/app/setting")
    @Produces(MediaType.APPLICATION_JSON)
    public String appSetting(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<String, AppSettingVO>(user).run(getSalarySystemConfigWrapper(user)::appSetting);
    }

    /**
     * 加密设置的进度
     *
     * @param request
     * @param response
     * @return
     */
    @GET
    @Path("/app/getEncryptProgress")
    @Produces(MediaType.APPLICATION_JSON)
    public String getEncryptProgress(@Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam(value = "progressId") String progressId) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<String, Map<String, Object>>(user).run(getSalarySystemConfigWrapper(user)::getEncryptProgress, progressId);
    }

    @POST
    @Path("/downloadConfig")
    @Produces(MediaType.APPLICATION_OCTET_STREAM)
    public Response downloadConfig(@Context HttpServletRequest request, @Context HttpServletResponse response) {
        try {
            User user = HrmUserVarify.getUser(request, response);
            SalaryConfig salaryConfig = getSalarySystemConfigWrapper(user).downloadConfig();

            String xml = XStreamUtil.marshal(salaryConfig);

            String fileName = "薪酬配置" + LocalDate.now();
            try {
                fileName = URLEncoder.encode(fileName + ".xml", "UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            StreamingOutput output = outputStream -> {
                Writer writer = new BufferedWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
                writer.write(xml);
                writer.flush();
            };


            response.setContentType("application/octet-stream");
            return Response.ok(output).header("Content-disposition", "attachment;filename=" + fileName).header("Cache-Control", "no-cache").build();
        } catch (Exception e) {
            log.error("下载薪酬配置", e);
            throw new RuntimeException("下载薪酬配置", e);
        }
    }

    @POST
    @Path("/uploadConfig")
    @Produces(MediaType.APPLICATION_JSON)
    public String initConfig(@Context HttpServletRequest request, @Context HttpServletResponse response, @RequestBody UploadConfigParam param) {
        User user = HrmUserVarify.getUser(request, response);
        return new ResponseResult<UploadConfigParam, UploadConfigResponse>(user).run(getSalarySystemConfigWrapper(user)::uploadConfig, param);

    }

}
